// Created Time:    2023-10-06 01:27:34
// Modified Time:   2023-10-06 01:31:00
#include<iostream>

using namespace std;

namespace Mango
{
template<class T>
class auto_ptr
{
public:
  auto_ptr(T* ptr) :_ptr(ptr)
  {}
  ~auto_ptr()
  {
    if(_ptr != nullptr)
    {
      delete _ptr;
    }
    _ptr = nullptr;
  }
  auto_ptr( auto_ptr<T>& ap):_ptr(ap._ptr)
  {
    ap._ptr = nullptr;
  }
  auto_ptr<T>& operator=( auto_ptr<T>& ap)
  {
    if(this != &ap)
    {
      delete _ptr; 
      _ptr = ap._ptr;
      ap._ptr = nullptr;
    }
    return *this;
  }
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }
private:
  T* _ptr;
};

template<class T>
class unique_ptr
{
public:
  unique_ptr(const T* ptr = nullptr) :_ptr(ptr)
  {}
  ~unique_ptr()
  {
    if(_ptr) delete _ptr;
    _ptr = nullptr;
  }
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }
  
  unique_ptr(const unique_ptr<T>&& sp) :_ptr(nullptr)
  {
    ::swap(sp._ptr,_ptr);
  }
  unique_ptr<T>& operator=(const unique_ptr<T>&& sp)
  {
    if(this != &sp)
    {
      ::swap(sp._ptr,_ptr);
    }
    return *this;
  }

  unique_ptr(const unique_ptr<T>&) = delete;
  unique_ptr<T>& operator=(const unique_ptr<T>&) = delete;
private:
  T* _ptr;
};
template<class T>
class shared_ptr
{
public:
  T* operator->()
  {
    return _ptr;
  }
  T& operator*()
  {
    return *_ptr;
  }

private:
  T* _ptr;
};


template<class T>
class weak_ptr
{
public:

private:
  T* _ptr;
};
}

